import { MenuService } from './../../../../../services/menu.service';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { Component, Input, OnInit } from '@angular/core';
import { ZepridePage, ZeprideTemplateComponent, WorkflowNodeItem, ZepridePageTemplate, ZeprideWorkflow } from 'src/app/models';
import { Menu } from 'src/app/models/menu';
import { PermitItem } from 'src/app/models/permitItem';
import { WorkflowService, PageService } from 'src/app/services';
import { PermitService } from 'src/app/services/permit.service';
import { WorkflowNodeService } from 'src/app/services/workflow-node.service';

@Component({
  selector: 'zepride-permit-perview-modal',
  templateUrl: './permit-perview-modal.component.html',
  styleUrls: ['./permit-perview-modal.component.less']
})
export class PermitPerviewModalComponent implements OnInit {
  @Input() mode: 'check' | 'preview' = 'check';
  @Input() userPermits: PermitItem[];
  @Input() authObjectId: string;
  searchValue;
  loading = true;

  menuList: Menu[];
  parentMenus: Menu[];
  childrenMenus: Menu[];

  workflowList: ZeprideWorkflow[] = [];
  pageList: ZepridePage[] = [];

  curWorkflow: ZeprideWorkflow;
  curPage: ZepridePage;

  tmpComItemList: ZeprideTemplateComponent[] = [];
  curTmpComItems: ZeprideTemplateComponent[] = [];

  sourceTmpComItemList: ZeprideTemplateComponent[] = [];
  sourceMenuList: Menu[];
  sourceWorkflowList: ZeprideWorkflow[];
  sourcePageList: ZepridePage[];


  constructor(
    private menuSvr: MenuService,
    private workflowSvr: WorkflowService,
    private pageSvr: PageService,
    private wnodeSvr: WorkflowNodeService,
    private permitSvr: PermitService,
    private modalRef: NzModalRef
  ) { }

  async ngOnInit() {
    if (!this.userPermits) {
      const orgId = localStorage.getItem('orgid');
      let queryParams: any = { orgId };
      if (this.authObjectId) {
        queryParams.authObjectId = this.authObjectId;
      }
      this.userPermits = await this.permitSvr.queryAccountPermits(queryParams);
    }

    await this.getMenuList();
    await this.getOrgPermits(this.tmpComItemList, this.workflowList, this.pageList, this.menuList);

    this.selectMenu();

    this.loading = false;
  }

  selectMenu() {
    this.parentMenus = this.menuList.filter(x => !x.parentId) as Menu[];
    if (this.parentMenus[0]) {
      (<any>this.parentMenus[0]).selected = true;
      this.menusClick(this.parentMenus[0], true);
    }
  }

  async searchChange() {
    await this.getOrgPermits(this.sourceTmpComItemList, this.sourceWorkflowList, this.sourcePageList, this.sourceMenuList, this.searchValue);
    this.selectMenu();
  }

  async getOrgPermits(tmpComItems: ZeprideTemplateComponent[], workflowList: ZeprideWorkflow[], pageList: ZepridePage[], menuList: Menu[], searchValue?: string) {
    tmpComItems = JSON.parse(JSON.stringify(tmpComItems));
    pageList = JSON.parse(JSON.stringify(pageList));
    workflowList = JSON.parse(JSON.stringify(workflowList));

    this.tmpComItemList = tmpComItems.filter(tmpComItem => {
      if (tmpComItem.component.perimitConfig && tmpComItem.component.perimitConfig.length == 0) {
        return false;
      }

      if (this.mode == 'check') {
        const r = tmpComItem.component.perimitConfig.every(pitem => {
          return this.userPermits.find(x => x.refObjectId == tmpComItem.id && x.permitId == pitem.permitId);
        });

        return !r;
      }
      else if (this.mode == 'preview') {
        tmpComItem.component.perimitConfig = tmpComItem.component.perimitConfig.filter(pitem => {
          return this.userPermits.find(x => x.refObjectId == tmpComItem.id && x.permitId == pitem.permitId);
        });

        let r = tmpComItem.component.perimitConfig.length > 0;
        if (searchValue) {
          r = (tmpComItem.component.perimitConfig.length > 0) && (tmpComItem.component.name.indexOf(searchValue) > -1);
        }

        return r;
      }

    });

    this.pageList = pageList.filter(page => {
      page.pageTmpItems = page.pageTmpItems.filter(pageTmpItem => pageTmpItem.template.tmpComItems.some(tmpComItem => this.tmpComItemList.find(x => x.id == tmpComItem.id)));
      return page.pageTmpItems.length > 0;
    });

    this.workflowList = workflowList.filter(workflow => {
      workflow.workflowNodeItems = workflow.workflowNodeItems.filter(node => {
        return this.pageList.find(x => x.flowNodeId == node.flowNodeId)
      });

      return workflow.workflowNodeItems.length > 0;
    })

    this.menuList = menuList.filter(menu => {
      if (menu.workflowId) {
        return this.workflowList.find(x => x.id == menu.workflowId);
      }
      else if (menu.pageId) {
        return this.pageList.find(x => x.id == menu.pageId);
      }
      else {
        return false;
      }
    });
  }

  ok() {
    this.modalRef.close();
  }
  cancel() {
    this.modalRef.close();
  }

  async getMenuList() {
    const result = await this.menuSvr.queryMenus();
    this.menuList = result.list as Menu[];

    const reqMenuPromiseList = [];
    for (let menu of this.menuList) {
      reqMenuPromiseList.push(this.reqMenuHandle(menu));
    }
    await Promise.all(reqMenuPromiseList);

    this.sourceMenuList = [...this.menuList];

    const getFlowNodePromiseList: Promise<void>[] = [];
    for (const workflow of this.workflowList) {
      for (const flowNode of workflow.workflowNodeItems) {
        getFlowNodePromiseList.push(this.getFlowNodePromiseHandle(flowNode));
      }
    }

    await Promise.all(getFlowNodePromiseList);

    this.sourceWorkflowList = [...this.workflowList];

    for (const page of this.pageList) {
      for (const pageTmpItem of page.pageTmpItems) {
        this.tmpComItemList = this.tmpComItemList.concat(pageTmpItem.template.tmpComItems);
      }
    }
    this.sourcePageList = [...this.pageList];
    this.sourceTmpComItemList = [...this.tmpComItemList];
  }

  private async getFlowNodePromiseHandle(flowNode) {
    const fn = await this.wnodeSvr.getFlowNodeById(flowNode.flowNodeId);
    if (fn.pages.length) {
      this.pageList.push(<any>fn.pages[0]);
    }
  }

  private async reqMenuHandle(menu) {
    if (menu.workflowId) {
      const wf = await this.workflowSvr.getWorkflowById(menu.workflowId);
      this.workflowList.push(wf);
    }
    else if (menu.pageId) {
      const page = await this.pageSvr.getPageById(menu.pageId);
      this.pageList.push(page);
    }
  }

  menusClick(item: Menu, isParent: boolean) {
    this.menuList.forEach(x => (<any>x).selected = false);
    if (isParent) {
      this.childrenMenus = this.menuList.filter(x => x.parentId == item.id);
    }

    this.curWorkflow = null;
    this.curPage = null;
    if (item.workflowId) {
      this.curWorkflow = this.workflowList.find(x => x.id == item.workflowId);
      this.flowNodeClick(this.curWorkflow.workflowNodeItems[0]);
    }
    else if (item.pageId) {
      this.curPage = this.pageList.find(x => x.id == item.pageId);
      if (this.curPage && this.curPage.pageTmpItems[0]) {
        this.pageTmpClick(this.curPage.pageTmpItems[0]);
      }

    }

    (<any>item).selected = true;
  }

  flowNodeClick(item: WorkflowNodeItem) {
    this.curWorkflow.workflowNodeItems.forEach(x => (<any>x).selected = false);
    (<any>item).selected = true;

    this.curPage = this.pageList.find(x => x.flowNodeId == item.flowNodeId);

    this.pageTmpClick(this.curPage.pageTmpItems[0]);
  }

  pageTmpClick(item: ZepridePageTemplate) {
    this.curPage.pageTmpItems.forEach(n => { (<any>n).selected = false });
    (<any>item).selected = true;

    this.curTmpComItems = this.tmpComItemList.filter(x => x.templateId == item.templateId);
  }
}
